window.onload = function () {
    if (document.body.contains(document.goSearch)) {
        var loaded = false;
        document.goSearch.onsubmit = function () { return goSearchNow() };

        /*
        Source:
          - https://github.com/nextapps-de/flexsearch#index-documents-field-search
          - https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html
          - http://elasticlunr.com/
          - https://pagefind.app/
          - https://github.com/getzola/zola/blob/master/docs/static/search.js
          - https://github.com/aaranxu/adidoks/blob/main/static/js/search.js
        */
        (function () {
            //insertHere

            function inputFocus(e) {

                if (e.keyCode === 191//forward slash
                    && document.activeElement.tagName !== "INPUT"
                    && document.activeElement.tagName !== "TEXTAREA") {
                    e.preventDefault();
                    searchinput.focus();
                    suggestions.classList.remove('d-none');
                }

                if (e.keyCode === 27) {//escape
                    searchinput.blur();
                    suggestions.classList.add('d-none');
                    closeAllLists();
                }

                const focusableSuggestions = suggestions.querySelectorAll('a');
                if (suggestions.classList.contains('d-none')
                    || focusableSuggestions.length === 0) {
                    return;
                }
                const focusable = [...focusableSuggestions];
                const index = focusable.indexOf(document.activeElement);

                let nextIndex = 0;

                if (e.keyCode === 38) {//up arrow
                    e.preventDefault();
                    nextIndex = index > 0 ? index - 1 : 0;
                    focusableSuggestions[nextIndex].focus();
                }
                else if (e.keyCode === 40) {//down arrow
                    e.preventDefault();
                    nextIndex = index + 1 < focusable.length ? index + 1 : index;
                    focusableSuggestions[nextIndex].focus();
                }

            }

            var suggestions = document.getElementById("suggestions");
            var searchinput = document.getElementById("searchinput");
            var lang = document.documentElement.getAttribute("lang");
            var langOnly = lang.substring(0, 2);
            var baseUrl = document.querySelector("meta[name='base']").getAttribute("content");
            if (baseUrl.slice(-1) == "/") {
                baseUrl = baseUrl.slice(0, -1);
            }
            options({//pagefind options
                basePath: baseUrl + '/js/'
            });
            var index;
            searchinput.addEventListener('input', show_results, true);
            suggestions.addEventListener('click', accept_suggestion, true);
            document.addEventListener("keydown", inputFocus);
            document.addEventListener("click", function (event) { suggestions.contains(event.target) || suggestions.classList.add("d-none") });
            document.getElementById('searchinput').onfocus = function() {
                if (!loaded) {
                    lazyLoad();
                    loaded = true;
                }
                document.getElementById('searchinput').onfocus = '';
            }
            async function lazyLoad() {
                await init();
            }

            // in page results when press enter or click search icon from search box
            function closeSearchNow() {
                const main = document.querySelector("main");
                main.innerHTML = window.main
            }

            function goSearchNow() {
                const main = document.querySelector("main");
                if (!window.main) {
                    window.main = main.innerHTML
                };
                var results = document.getElementById("suggestions");// suggestions div generated by search box

                var ResultsClone = results.cloneNode(true);// make a clone of the results, so that we can alter it
                ResultsClone.id = "results";// alter the id of our clone, so that we can apply different css style

                var headerDiv = document.createElement("div");// create a div element

                var headerContent = '<form name="closeSearch"><h2><button type="submit" title="Close Search"><i class="svgs x"></i></button> <i class="svgs search"></i> '.concat(document.getElementById("searchinput").value, "</h2></form>");// header to use at top of results page

                headerDiv.innerHTML = headerContent;// document element div (headerDiv), set the inner contents to our header html (headerContent)

                ResultsClone.insertBefore(headerDiv, ResultsClone.firstChild);//insert our header div at the top of the page

                main.innerHTML = ResultsClone.outerHTML;//display ResultsClone.outerHTML as the page
                results.innerHTML = "";// clear the suggestions div popup
                document.getElementById("searchinput").value = "";// clear the search input box
                document.body.contains(document.closeSearch) && (document.closeSearch.onsubmit = function () { closeSearchNow() })
                return false
            }

            /* Close search suggestion popup list */
            function closeAllLists(elmnt) {
                var suggestions = document.getElementById("suggestions");
                while (suggestions.firstChild) {
                    suggestions.removeChild(suggestions.firstChild);
                }
            }



            async function show_results() {
                var value = this.value.trim();

                var searchResults = await search(value);

                var entry, childs = suggestions.childNodes;
                var i = 0, len = searchResults.results.length;
                var items = value.split(/\s+/);
                suggestions.classList.remove('d-none');

                for (const result of searchResults.results) {
                    const data = await result.data();
                    if (data.content !== '') {
                        entry = document.createElement('div');

                        entry.innerHTML = '<a href><span></span><span></span></a>';

                        a = entry.querySelector('a'),
                            t = entry.querySelector('span:first-child'),
                            d = entry.querySelector('span:nth-child(2)');
                        a.href = data.url;
                        t.textContent = data.meta.title;
                        d.innerHTML = sanitise(data.excerpt);

                        suggestions.appendChild(entry);
                    }
                }

                while (childs.length > len) {
                    suggestions.removeChild(childs[i])
                }
            }

            function sanitise(str) {
                return str.replace(/\{\{.*?\}\}|—|<(?!\/?mark\b).*?>|&lt;.*?&gt;/g, '');
            }


            function accept_suggestion() {

                while (suggestions.lastChild) {

                    suggestions.removeChild(suggestions.lastChild);
                }

                return false;
            }
            // Get the string bytes from binary
            function getByteByBinary(binaryCode) {
                // Binary system, starts with `0b` in ES6
                // Octal number system, starts with `0` in ES5 and starts with `0o` in ES6
                // Hexadecimal, starts with `0x` in both ES5 and ES6
                var byteLengthDatas = [0, 1, 2, 3, 4];
                var len = byteLengthDatas[Math.ceil(binaryCode.length / 8)];
                return len;
            }

            // Get the string bytes from hexadecimal
            function getByteByHex(hexCode) {
                return getByteByBinary(parseInt(hexCode, 16).toString(2));
            }
            // Get substring by bytes
            // If using JavaScript inline substring method, it will return error codes
            // Source: https://www.52pojie.cn/thread-1059814-1-1.html
            function substringByByte(str, maxLength) {
                var result = "";
                var flag = false;
                var len = 0;
                var length = 0;
                var length2 = 0;
                for (var i = 0; i < str.length; i++) {
                    var code = str.codePointAt(i).toString(16);
                    if (code.length > 4) {
                        i++;
                        if ((i + 1) < str.length) {
                            flag = str.codePointAt(i + 1).toString(16) == "200d";
                        }
                    }
                    if (flag) {
                        len += getByteByHex(code);
                        if (i == str.length - 1) {
                            length += len;
                            if (length <= maxLength) {
                                result += str.substr(length2, i - length2 + 1);
                            } else {
                                break
                            }
                        }
                    } else {
                        if (len != 0) {
                            length += len;
                            length += getByteByHex(code);
                            if (length <= maxLength) {
                                result += str.substr(length2, i - length2 + 1);
                                length2 = i + 1;
                            } else {
                                break
                            }
                            len = 0;
                            continue;
                        }
                        length += getByteByHex(code);
                        if (length <= maxLength) {
                            if (code.length <= 4) {
                                result += str[i]
                            } else {
                                result += str[i - 1] + str[i]
                            }
                            length2 = i + 1;
                        } else {
                            break
                        }
                    }
                }
                return result;
            }
            /* Taken from mdbook
            // The strategy is as follows:
            // First, assign a value to each word in the document:
            //  Words that correspond to search terms (stemmer aware): 40
            //  Normal words: 2
            //  First word in a sentence: 8
            // Then use a sliding window with a constant number of words and count the
            // sum of the values of the words within the window. Then use the window that got the
            // maximum sum. If there are multiple maximas, then get the last one.
            // Enclose the terms in <b>.
            */

            document.goSearch.onsubmit = function () { return goSearchNow() };
        }());
    }
};
